package com.neusoft.neuiotms.dcom.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityNotFoundException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.dcom.converter.DutyArrangementConverter;
import com.neusoft.neuiotms.dcom.dto.DutyArrangementDTO;
import com.neusoft.neuiotms.dcom.dto.DutyArrangementGroupDTO;
import com.neusoft.neuiotms.dcom.dto.DutyArrangementResultDTO;
import com.neusoft.neuiotms.dcom.dto.ShiftDTO;
import com.neusoft.neuiotms.dcom.model.DutyArrangement;
import com.neusoft.neuiotms.dcom.repository.DutyArrangementRepository;
import com.neusoft.neuiotms.dcom.service.DutyArrangementResultService;
import com.neusoft.neuiotms.dcom.service.DutyArrangementService;
import com.neusoft.neuiotms.dcom.service.ShiftService;

@Service
public class DutyArrangementServiceImpl implements DutyArrangementService {

    @Autowired
    private DutyArrangementConverter dutyArrangementConverter;
    @Autowired
    private DutyArrangementRepository dutyArrangementRepository;
    @Autowired
    private DutyArrangementResultService dutyArrangementResultService;
    @Autowired
    private ShiftService shiftService;

    @Override
    public List<DutyArrangementDTO> index(final Searchable searchable) {
        final List<DutyArrangement> result = this.dutyArrangementRepository.index(searchable);
        return this.dutyArrangementConverter.toListDTO(result);
    }

    @Override
    public Page<DutyArrangementDTO> search(final Pageable pageable, final Searchable searchable) {
        final Page<DutyArrangement> result = this.dutyArrangementRepository.search(pageable, searchable);
        return this.dutyArrangementConverter.toPageDTO(result);
    }

    @Transactional
    @Override
    public DutyArrangementDTO create(final DutyArrangementDTO dto) {
        DutyArrangement model = this.dutyArrangementConverter.toModel(dto);
        model = this.dutyArrangementRepository.save(model);

        // 生成排班结果
        this.dutyArrangementResultService.createResults(model.getId());
        return this.dutyArrangementConverter.toDTO(model);
    }

    @Override
    public DutyArrangementDTO update(final Long id, final DutyArrangementDTO dto) {

        DutyArrangement model;
        try {
            model = this.dutyArrangementRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        dto.setId(model.getId());
        model = this.dutyArrangementConverter.toModel(dto);
        this.dutyArrangementRepository.save(model);
        return this.dutyArrangementConverter.toDTO(model);
    }

    @Transactional
    @Override
    public DutyArrangementDTO update(final Long id, final List<DutyArrangementGroupDTO> dtos) {

        DutyArrangement model;
        try {
            model = this.dutyArrangementRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        final Map<Long, Integer> map = new HashMap<>();
        final Map<Integer, Long> reverseMap = new HashMap<>();

        dtos.stream().forEach(k -> {
            map.put(k.getTeamGroupId(), k.getGroupNumber());
            reverseMap.put(k.getGroupNumber(), k.getTeamGroupId());
        });

        final Map<Long, Long> orderMap = new HashMap<>();

        model.getGroups().forEach(k -> {
            orderMap.put(k.getTeamGroup().getId(), reverseMap.get(k.getGroupNumber()));
            k.setGroupNumber(map.containsKey(k.getTeamGroup().getId()) ? map.get(k.getTeamGroup().getId()) : 0);
        });

        // 调整排班
        this.dutyArrangementResultService.groupOrder(model.getId(), orderMap);

        // 保存互换结果
        this.dutyArrangementRepository.save(model);

        return this.dutyArrangementConverter.toDTO(model);
    }

    @Override
    public DutyArrangementDTO details(final Long id) {

        DutyArrangement model;
        try {
            model = this.dutyArrangementRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        return this.dutyArrangementConverter.toDTO(model);
    }

    @Transactional
    @Override
    public void delete(final Long id) {

        Boolean flag = true;

        final List<Long> deleteList = new ArrayList<>();
        final List<Long> deleteShiftList = new ArrayList<>();

        // 校验是否含有以前的数据
        final Searchable searchable = new Searchable();
        searchable.put("dutyArrangementId", id);
        final List<DutyArrangementResultDTO> list = this.dutyArrangementResultService.index(searchable);

        // 过滤时间段的数据
        list.stream().filter(k -> k.getStartTime().getTime() > new Date().getTime()).map(s -> s.getId())
                .forEach(deleteList::add);

        if (deleteList.size() != list.size()) {
            flag = false;
        }

        deleteList.forEach(k -> {
            this.dutyArrangementResultService.delete(k);
        });

        // 过滤换班情况
        final List<ShiftDTO> shiftList = this.shiftService.index(searchable);
        shiftList.stream().filter(k -> k.getStartTime().getTime() > new Date().getTime()).map(s -> s.getId())
                .forEach(deleteShiftList::add);

        if (deleteShiftList.size() != shiftList.size()) {
            flag = false;
        }

        deleteShiftList.forEach(k -> {
            this.shiftService.delete(k);
        });

        if (flag) {
            this.dutyArrangementRepository.deleteById(id);
        } else {

            DutyArrangement model;
            try {
                model = this.dutyArrangementRepository.getOne(id);
            } catch (final EntityNotFoundException e) {
                throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
            }

            model.setDeleteFlag(true);
            this.dutyArrangementRepository.save(model);
        }

    }

}
